
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Netty的协议编解码 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>Netty的协议编解码 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">Netty协议编解码中的“编码”（Encoder）和“解码”（Decoder）分别指什么过程？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">编码（Encoder）是将 Java 对象转换为字节流（即网络传输的二进制数据）的过程；解码（Decoder）则是将字节流转换回 Java 对象的过程。</div>
          </div>
          <div class="card-source">来源: 1. Netty 编解码的基本概念</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在Netty中，用于实现编解码功能的核心组件是什么？以及推荐用于实现编码和解码的基础类分别是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Netty主要使用 `ChannelHandler` 来实现编解码功能。用于编码的基础类是 `MessageToByteEncoder`，它将Java对象编码为字节流；用于解码的基础类是 `ByteToMessageDecoder`，它将字节流解码为Java对象。</div>
          </div>
          <div class="card-source">来源: 1. Netty 编解码的基本概念</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在实现 `ByteToMessageDecoder` 时，如果接收到的 `ByteBuf` 数据不足以构成一个完整的消息，应该如何处理？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">在 `decode()` 方法中，首先应检查 `ByteBuf` 中是否有足够的数据进行解码。如果数据不足，则应该直接返回，等待更多的数据到达后再进行处理。</div>
          </div>
          <div class="card-source">来源: 3. 解码器（Decoder）实现</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">Netty中的 `ChannelPipeline` 是什么？编解码器是如何在其中工作的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`ChannelPipeline` 是一个处理器链，所有数据处理逻辑都通过它传递。编解码器作为 `ChannelHandler` 被添加到 `ChannelPipeline` 中。当数据接收时，会先通过解码器处理；当数据发送时，会通过编码器处理。</div>
          </div>
          <div class="card-source">来源: 4. `ChannelPipeline` 中的编解码流程</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在Netty中，哪个类是处理字节流的核心数据容器，并且在编解码中扮演了什么角色？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`ByteBuf` 是Netty中处理字节流的核心类。在编码过程中，编码器将Java对象的数据写入 `ByteBuf`；在解码过程中，解码器从 `ByteBuf` 中读取字节数据并转换为Java对象。</div>
          </div>
          <div class="card-source">来源: 5. `ByteBuf` 在编解码中的作用</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">当一个出站（outbound）的Java对象（如MyMessage）在 `ChannelPipeline` 中传递时，它会经过哪个处理器，并发生什么转换？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">当一个 `MyMessage` 对象需要发送时，它会通过 `MyMessageEncoder`（编码器）进行处理。编码器会将其转换为字节流并写入 `ByteBuf` 中，以便通过网络发送出去。</div>
          </div>
          <div class="card-source">来源: 4. `ChannelPipeline` 中的编解码流程</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">在 `ByteToMessageDecoder` 的 `decode` 方法中，解码成功后的Java对象应该被放置在哪里，以便下游的处理器继续处理？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">解码成功后的Java对象（例如 `MyMessage` 对象）应该被添加到 `decode` 方法的 `out` 参数（一个 `List<Object>` 类型）中，这样它就可以被传递给 `ChannelPipeline` 中的下一个处理器使用。</div>
          </div>
          <div class="card-source">来源: 3. 解码器（Decoder）实现</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">如何实现一个自定义的Netty编码器，例如将一个包含ID和Name的 `MyMessage` 对象进行编码？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">可以通过继承 `MessageToByteEncoder<MyMessage>` 类，并重写 `encode` 方法。在该方法内，使用 `ByteBuf` 提供的API（如 `out.writeInt()` 和 `out.writeCharSequence()`）将 `MyMessage` 对象的字段按顺序写入到 `ByteBuf` 中。</div>
          </div>
          <div class="card-source">来源: 2. 编码器（Encoder）实现</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">请描述一个网络数据包到达Netty应用后，在 `ChannelPipeline` 中经历解码并被业务逻辑处理的完整流程。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. 数据接收：当数据从网络中接收到时，首先被 `MyMessageDecoder` 拦截并解码，将 `ByteBuf` 转换为 `MyMessage` 对象。2. 数据传输：解码后的 `MyMessage` 对象会沿着 `ChannelPipeline` 传递给下一个处理器进行进一步的业务处理。</div>
          </div>
          <div class="card-source">来源: 4. `ChannelPipeline` 中的编解码流程</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
